/**
 * @description:
 * @title: StackOverFlowErrorDemo
 * @author: zp
 * @date: 2021/8/10 21:07
 * 常见的几种JVM的错误
 *  java.lang.StackOverflowError
 *      1.2 原因分析
 *      无限递归循环调用（最常见原因），要时刻注意代码中是否有了循环调用方法而无法退出的情况
 *      执行了大量方法，导致线程栈空间耗尽
 *      方法内声明了海量的局部变量
 *      native 代码有栈上分配的逻辑，并且要求的内存还不小，比如 java.net.SocketInputStream.read0 会在栈上要求分配一个 64KB 的缓存（64位 Linux）
 * java.lang.OutOfMemoryError: Java heap space
 *      2.2 原因分析
 *      请求创建一个超大对象，通常是一个大数组
 *      超出预期的访问量/数据量，通常是上游系统请求流量飙升，常见于各类促销/秒杀活动，可以结合业务流量指标排查是否有尖状峰值
 *      过度使用终结器（Finalizer），该对象没有立即被 GC
 *      内存泄漏（Memory Leak），大量对象引用没有释放，JVM 无法对其自动回收，常见于使用了 File 等资源没有回收
 * java.lang.OutOfMemoryError: GC overhead limit exceeded
 *      （1）假如不抛出 GC overhead limit exceeded 错误，那 GC 清理的那么一丢丢内存很快就会被再次填满，迫使 GC 再次执行，这样恶性循环，CPU 使用率 100%，而 GC 没什么效果。
 *      （2）JVM 内置了垃圾回收机制GC，所以作为 Javaer 的我们不需要手工编写代码来进行内存分配和释放，
 *          但是当 Java 进程花费 98% 以上的时间执行 GC，但只恢复了不到 2% 的内存，
 *          且该动作连续重复了 5 次，就会抛出 java.lang.OutOfMemoryError:GC overhead limit
 * java.lang.OutOfMemoryError: Direct buffer memory
 *      我们使用 NIO 的时候经常需要使用 ByteBuffer 来读取或写入数据，这是一种基于 Channel(通道) 和 Buffer(缓冲区)的 I/O 方式，
 *      它可以使用 Native 函数库直接分配堆外内存，然后通过一个存储在 Java 堆里面的 DirectByteBuffer
 *      对象作为这块内存的引用进行操作。这样在一些场景就避免了 Java 堆和 Native 中来回复制数据，所以性能会有所提高。
 * java.lang.OutOfMemoryError: unable to create new native thread 无法创建本地线程
 *      每个 Java 线程都需要占用一定的内存空间，当 JVM 向底层操作系统请求创建一个新的 native 线程时，如果没有足够的资源分配就会报此类错误。
 *       linux系统默认用户创建限制1024（root 无上限 可以配置）
 * java.lang.OutOfMemoryError：Metaspace
 *      （1）JDK 1.8 之前会出现 Permgen space，该错误表示永久代（Permanent Generation）已用满，
 *         通常是因为加载的 class 数目太多或体积太大。随着 1.8 中永久代的取消，就不会出现这种异常了。
 *      （2）Metaspace 是方法区在 HotSpot 中的实现，它与永久代最大的区别在于，元空间并不在虚拟机内存中而是使用本地内存
 *        ，但是本地内存也有打满的时候，所以也会有异常。
 * java.lang.OutOfMemoryError: Requested array size exceeds VM limit
 *      JVM 限制了数组的最大长度，该错误表示程序请求创建的数组超过最大长度限制。
 *      JVM 在为数组分配内存前，会检查要分配的数据结构在系统中是否可寻址，通常为 Integer.MAX_VALUE-2。
 *      此类问题比较罕见，通常需要检查代码，确认业务是否需要创建如此大的数组，是否可以拆分为多个块，分批执行。
 * java.lang.OutOfMemoryError: Out of swap space
 *      该错误表示所有可用的虚拟内存已被耗尽。虚拟内存（Virtual Memory）由物理内存（Physical Memory）和交换空间（Swap Space）两部分组成。
 * java.lang.OutOfMemoryError：Kill process or sacrifice child
 *      默认情况下，Linux 内核允许进程申请的内存总量大于系统可用内存，通过这种“错峰复用”的方式可以更有效的利用系统资源。
 *      然而，这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存，然后导致其他进程没有可用内存。此时，
 *      系统将自动激活 OOM Killer，寻找评分低的进程，并将其“杀死”，释放内存资源。
 */
public class StackOverFlowErrorDemo {
    public static void main(String[] args) {
        //StackOverFlowError();
    }

    private static void StackOverFlowError() {
        //java.lang.StackOverflowError StackOverFlowErrorDemo.StackOverFlowError
        StackOverFlowError();
    }
}
